We know that we can use an interrupt signal to stop the foreground program and perform another piece of code. In our case we want use an interrupt to refresh the LEDs at regular intervals. However, at the moment we don't know how to cause the interrupt. This problem is solved by another hardware component in the PICmicro, the timer. This is simply an eight bit counter. It counts up at a particular rate and when it wraps round (i.e. goes from 0xff to 0x00) it can be made to cause an interrupt. The counter "ticks" at the PICmicro clock frequency divided by four. This is because the PICmicro takes four clock ticks to obey a single instruction, and the clock ticks at the rate instructions are performed.

You can control the rate at which the timer counts, i.e. how long it takes to wrap round, by means of a pre-scaler. This is a hardware device which divides the clock coming into the timer by a particular power of two. If the prescaler is set to 2 the timer is clocked at half speed, if the prescaler is set to 4 the timer is clocked at quarter speed, and so on. The PICmicro gives us a pre-scaler so that we can control how long it takes the counter to overflow.

We will look at the programming of the prescaler a little later, for now we can pick a value which gives us a resonable refresh rate without taking too much time away from the foreground program. The value I have chosen gives an interrupt of 200 Hz. This means that we will get round all of the LEDs in 200/4 = 50Hz. This is the same frequency as domestic lighting and so to the human eye is completely flicker free.

The code on the right turns on the interrupts and puts a call of the refresh function in the timer interrupt handler. Note that in the main function the code actually does nothing and yet the lights still work!

If you load and run Exercise 4.4 you will find that the numbers are displayed without the foreground program doing anything!

You can use the timer interrupt for anything which needs to happen at regular intervals. It can serve as a replacement for the delay loops which we use for our music program, and also allow notes to continue playing a sound while the program does something else.

Foreground and Background

I call the program which is actually running (i.e. the contents of the main function) the foreground process and the code which runs on the interrupts the background process.

You have to be careful how the foreground and background processes interact. At the moment our foreground function does nothing, in that it is just a while loop with no contents. If it was to change variables used by the timer interrupt, in this case the variable led_counter, it could interfere with the screen refresh.

When you use interrupts in this way it is important that you set up well defined connections between the foreground and background processes. In this case we use the array which holds the patterns for each LED as the communications medium. We also know that the foreground only ever puts values into the array, and the background only ever reads them. If we want to have communication in both directions between the foreground and background processes you must be careful how you synchronise it.

Operating systems like Windows 98, NT and Linux use the timer interrupt to switch execution between more than one "simultaneously" executing program. You can also do this kind of thing in the PICmicro if you wish.

Accessing INTCON

In the PIC, interrupts are controlled using the INTCON register, which lives in the same area as the other registers we've used so far, such as PORTA and TRISB.

For full details, look in the C programming section at 'C and hardware'